package org.hackystat.devcathlon.event;

import java.util.logging.Logger;
import javax.xml.datatype.XMLGregorianCalendar;

import org.hackystat.devcathlon.configuration.ConfigurationException;
import org.hackystat.devcathlon.configuration.ConfigurationManager;
import org.hackystat.devcathlon.configuration.jaxb.DevcathlonConfiguration;
import org.hackystat.devcathlon.configuration.jaxb.EventConfiguration;
import org.hackystat.devcathlon.match.Match;
import org.hackystat.devcathlon.team.Team;
import org.hackystat.utilities.logger.HackystatLogger;

/**
 * Provides the abstract class that is extended by all event instances. 
 * All Events must be able to produce an EventScore given a match and a team.
 * To get the actual points that an EventScore is worth, the Event can access information 
 * from the DevcathlonConfiguration.  
 * @author Philip Johnson
 */
public abstract class Event {
  
  /** Holds a pointer to the DevcathlonConfiguration instance for this system. */
  protected DevcathlonConfiguration config;
  /** Holds a pointer to the logger for this system. */ 
  protected Logger logger; 
  /** The unique name for this event. */
  protected String eventName;
  /** The wakeup interval (if any). */
  protected int wakeupInterval;
  /** The base score weight. */
  protected int baseScoreWeight;
  /** The event configuration for this event. */
  protected EventConfiguration eventConfig;
  /** The configuration manager. */
  protected ConfigurationManager configManager;

  /**
   * Instantiates an Event, initializing a pointer to the configuration and the logger.  
   * @param eventName The name of the event. 
   * @throws EventException If problems occur getting the configuration.
   */
  public Event (String eventName) throws EventException {
    this.eventName = eventName;
    this.configManager = ConfigurationManager.getInstance();
    
    try {
      this.config = configManager.getConfiguration();
      this.wakeupInterval = configManager.getWakeupInterval(this.eventName);
      this.baseScoreWeight = configManager.getBaseScoreWeight(this.eventName);
      this.eventConfig = configManager.getConfiguration(this.eventName);
    }
    catch (ConfigurationException e) {
      throw new EventException("Error processing configuration for " + eventName, e);
    }
    this.logger = HackystatLogger.getLogger("org.hackystat.devcathlon", "devcathlon");
  }
  

  /**
   * Returns an EventScore instance indicating the score achieved by the given team for the given
   * Match on this particular Event. 
   * @param match The match of interest. 
   * @param team The team whose score is to be computed.
   * @param timestamp The time at which this event is being run. 
   * @return The EventScore. 
   * @throws EventException If problems occur while processing this event. 
   */
  public abstract EventScore computeScore(Match match, Team team, XMLGregorianCalendar timestamp) 
  throws EventException;
  
  /**
   * Returns the number of points awarded to this Team for the passed EventScore.
   * The Event instance can consult the DevcathlonConfiguration to determine the points.  
   * @param score The EventScore whose points are to be determined. 
   * @return An integer indicating the points for this EventScore. 
   */
  public abstract int computePoints(EventScore score);
  
  /**
   * Returns the name of this Event. 
   * @return The name of this event. 
   */
  public String getName() {
    return this.eventName;
  }

}
